//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.eshop.common.utils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.eshop.annotation.Query;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class QueryHelpPlus {
    private static final Logger log = LoggerFactory.getLogger(QueryHelpPlus.class);

    public QueryHelpPlus() {
    }

    //R是要查询的数据类型，说直百点就是查哪个表   Q是定制的查询类，根据里面属性以及注解自动生成SQL去查询
    public static <R, Q> QueryWrapper getPredicate(R obj, Q query) {
        QueryWrapper<R> queryWrapper = new QueryWrapper();
        //如果查询类为空那直接返回一个空的wrapper就行了
        if (query == null) {
            return queryWrapper;
        } else {
            try {
                //获取出定制查询类的所有字段
                List<Field> fields = getAllFields(query.getClass(), new ArrayList());
                Iterator var4 = fields.iterator();

                while(true) {
                    while(var4.hasNext()) {
                        Field field = (Field)var4.next();
                        //暴力破解前，要先存False值，后面再把权限设置回去
                        boolean accessible = field.isAccessible();
                        //暴力破解
                        field.setAccessible(true);
                        //获取字段上的Query注解
                        Query q = field.getAnnotation(Query.class);
                        //判断该字段上是否有Query注解
                        if (q != null) {
                            //有的话就获取注解上的一些属性
                            String propName = q.propName();
                            //获取注解上想要进行的的模糊查询字段
                            String blurry = q.blurry();
                            //如果propName没有写上值，就直接用字段名作为attributeName
                            String attributeName = isBlank(propName) ? field.getName() : propName;
                            //给attributeName做驼峰转字符串转化
                            //attributeName就相当于数据库字段名
                            attributeName = humpToUnderline(attributeName);
                            //获取该字段的属性值
                            //之所以括号要加query，这是反射基本功，获取一个字段属性值你得指明它属于哪个对象吧
                            Object val = field.get(query);
                            //如果没有属性值那就可以溜了，继续遍历下一个字段
                            if (ObjectUtil.isNull(val) || "".equals(val)) {
                                continue;
                            }

                            // 拼接 or like 模糊查询
                            if (ObjectUtil.isNotEmpty(blurry)) {
                                String[] blurrys = blurry.split(",");
                                queryWrapper.and((wrapper) -> {
                                    for(int i = 0; i < blurrys.length; ++i) {
                                        String column = humpToUnderline(blurrys[i]);
                                        wrapper.or();
                                        wrapper.like(column, val.toString());
                                    }
                                });
                                continue;
                            }
                            //如果上面都没continue，就说明不是模糊查询，是其他类型
                            //通过@Query注解上的type属性判断是要进行什么类型的查询
                            switch(q.type()) {
                                case EQUAL:
                                    queryWrapper.eq(attributeName, val);
                                    break;
                                case GREATER_THAN:
                                    queryWrapper.ge(attributeName, val);
                                    break;
                                case GREATER_THAN_NQ: //大于等于
                                    queryWrapper.gt(attributeName, val);
                                    break;
                                case LESS_THAN:
                                    queryWrapper.le(attributeName, val);
                                    break;
                                case LESS_THAN_NQ:
                                    queryWrapper.lt(attributeName, val);
                                    break;
                                case INNER_LIKE: //like
                                    queryWrapper.like(attributeName, val);
                                    break;
                                case LEFT_LIKE: //把%加在左侧
                                    queryWrapper.likeLeft(attributeName, val);
                                    break;
                                case RIGHT_LIKE: //把%加在右侧
                                    queryWrapper.likeRight(attributeName, val);
                                    break;
                                case IN:
                                    if (CollUtil.isNotEmpty((Collection)val)) {
                                        queryWrapper.in(attributeName, (Collection)val);
                                    }
                                    break;
                                case NOT_EQUAL:
                                    queryWrapper.ne(attributeName, val);
                                    break;
                                case NOT_NULL:
                                    queryWrapper.isNotNull(attributeName);
                                    break;
                                case BETWEEN:
                                    List<Object> between = new ArrayList((List)val);
                                    queryWrapper.between(attributeName, between.get(0), between.get(1));
                                    break;
                                case UNIX_TIMESTAMP:
                                    //要求查询数据的时间在一段时间内
                                    List<Object> UNIX_TIMESTAMP = new ArrayList((List)val);
                                    if (!UNIX_TIMESTAMP.isEmpty()) {
                                        SimpleDateFormat fm = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                                        Date time1 = fm.parse(UNIX_TIMESTAMP.get(0).toString());
                                        Date time2 = fm.parse(UNIX_TIMESTAMP.get(1).toString());
                                        queryWrapper.between(attributeName, time1, time2);
                                    }
                            }
                        }
                        //重新设置好暴力破解的权限为false
                        field.setAccessible(accessible);
                    }
                    //将拼接好的wrapper返回回去
                    return queryWrapper;
                }
            } catch (Exception var19) {
                log.error(var19.getMessage(), var19);
                return queryWrapper;
            }
        }
    }

    private static boolean isBlank(final CharSequence cs) {
        int strLen;
        if (cs != null && (strLen = cs.length()) != 0) {
            for(int i = 0; i < strLen; ++i) {
                if (!Character.isWhitespace(cs.charAt(i))) {
                    return false;
                }
            }

            return true;
        } else {
            return true;
        }
    }

    private static List<Field> getAllFields(Class clazz, List<Field> fields) {
        if (clazz != null) {
            fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
            getAllFields(clazz.getSuperclass(), fields);
        }

        return fields;
    }

    //将驼峰字符串转成下划线字符串 如SystemGroupData 转换成 System_Group_Data
    public static String humpToUnderline(String para) {
        StringBuilder sb = new StringBuilder(para);
        int temp = 0;
        if (!para.contains("_")) {
            for(int i = 0; i < para.length(); ++i) {
                if (Character.isUpperCase(para.charAt(i))) {
                    sb.insert(i + temp, "_");
                    ++temp;
                }
            }
        }

        return sb.toString();
    }
}
